home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / misc / sci / RARS_Amiga_3.lha / RARS / dynamic.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-27  |  5.5 KB  |  126 lines

  1. // DYNAMIC.CPP - "driver" function for RARS - M. Timin, Feb. 1995
  2. // This robot has no static or global variables,
  3. // so it can drive any number of cars.  
  4. // There is a static and a global associated with passing the name,
  5. // but the calling program expects that and handles it OK.
  6. // adapted to ver. 0.39 3/6/95 by M. Timin
  7. // for ver. 0.60
  8.  
  9. // The language here can be considered to be ANSI C or C++.
  10.  
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <math.h>
  14. #include "car.h"
  15.  
  16. // These parameters may be adjusted to get better performance:
  17. const double CORN_SPD_CON = 6.1;   // determines how fast to take corners
  18. const double STEER_GAIN = 2.5;     // servo gain, for staying in "lane"
  19. const double STEER_DAMP = 1.5;     // servo damping, to prevent "weaving"
  20. const double END_ACCEL = .27; // we accelerate until this fraction of length
  21. const double END_CORNER = 2.5;// used to decide when to start leaving the corer
  22. const double ESC_ALPHA = .03; // after a crash, set alpha like this, + or -
  23. const double SLIP_LIM = 4.5;  // maximum wheel slip, ft/sec, in wheel_slip()
  24. const double SLIP_CON = 70.0; // sets power & slip during linear acceleration
  25.  
  26. // The following function calculates the speed for a corner.
  27. // The lateral force produced by cornering is proportional to the square
  28. // of the speed, and is inversely proportional to the radius of the path.
  29. // Therefore, the attainable cornering speed for differnt radii is
  30. // proportional to the square root of the radius.  This function implements
  31. // that rule.  The value to use for CORN_SPD_CON can be determined by
  32. // trial and error.  Example result: if the car is following a path with
  33. // radius of 100 ft, and if CORN_SPD_CON is 5.0, then crn_spd is 50 ft/sec.
  34. double crn_spd(double radius)
  35. {
  36.    if(radius < 0.0)         // change sign of negative radius
  37.       radius = -radius;
  38.    else if(radius == 0.0)   // This is just insurance, this funtion doesn't
  39.       return(200.0);        // make sense when the radius is zero.
  40.    return CORN_SPD_CON * sqrt(radius);
  41. }
  42.  
  43. // In order to set vc, if you know how fast you want to go (goal), and how
  44. // fast you are going now (present), This function will compute a reasonable
  45. // value for vc.  The value is never very far from the present speed, both
  46. // to attempt to stay within the power limit, and to maintain steering control.
  47. // You can adjust the resulting slip by changing SLIP_LIM.
  48. double wl_spd(double goal, double present)
  49. {
  50.    double ws;
  51.  
  52.    if(present > goal + 2 * SLIP_LIM)  // if too fast,
  53.       ws = present - SLIP_LIM;      // slow down.
  54.    else if(present < goal - 2 * SLIP_LIM)  // if too slow,
  55.       ws = present + SLIP_LIM;             // accelerate.
  56.    else                           // if quite close,
  57.       ws = (goal + present) / 2;      // approach desired speed gently.
  58.  
  59.    return ws;
  60. }
  61.  
  62. // The task of this function is to compute vc and alpha. 
  63. con_vec dynamic(situation & s)
  64. {
  65.    const char name[] = "Dynamic";      // This is the robot driver's name!
  66.    static int init_flag = 1;          // cleared by first call
  67.    double speed;                      // target speed for cornering, ft/sec
  68.    double speed_next;                 // target speed for next corner
  69.    con_vec result;                    // This is what is returned.
  70.    double width;                      // track width, feet
  71.    double alpha, vc;           // components of result
  72.    double arg;                 // for temporary storage of calculation
  73.  
  74.    // This paragraph has nothing to do with car control; it is just
  75.    // to identify the driver by copying its name to a global RAM area:
  76.    // This happens only on the very first call to this function
  77.    if(init_flag)  {            // first time through, only copy name:
  78.       my_name_is(name);        // copy the name string into the host program
  79.       init_flag = 0;
  80.       result.alpha = result.vc = 0;
  81.       return result;
  82.    }
  83.  
  84.    if(stuck(s.backward, s.v,s.vn, s.to_lft,s.to_rgt, &result.alpha,&result.vc))
  85.       return result;
  86.  
  87.    // Set alpha based on a servo-mechanism approach, trying to stay
  88.    // in the middle of the track, i.e., s.to_left equal to .5 * width:
  89.    width = s.to_lft + s.to_rgt;                        // find width of track
  90.    alpha = STEER_GAIN * (s.to_lft - .5 * width) / width;
  91.    alpha -= STEER_DAMP * s.vn / s.v;  // This is damping, to prevent oscillation
  92.  
  93.    // calculate target speeds for current corner and the next:
  94.    if(s.cur_rad == 0.0)
  95.       arg = 0.0;
  96.    else if(s.cur_rad > 0.0)
  97.       arg = s.cur_rad + .5 * width;
  98.    else
  99.       arg = s.cur_rad - .5 * width;
  100.    speed = crn_spd(arg);      // speed is based on radius
  101.  
  102.    if(s.nex_rad == 0.0)
  103.       arg = 0.0;
  104.    else if(s.nex_rad > 0.0)
  105.       arg = s.nex_rad + .5 * width;
  106.    else
  107.       arg = s.nex_rad - .5 * width;
  108.    speed_next = crn_spd(arg); // of center line of track.
  109.  
  110.    // now set the tire speed, vc:
  111.    if(s.cur_rad == 0.0)                  // If we are on a straightaway,
  112.       if(s.to_end > END_ACCEL * s.cur_len) // if we are far from the end,
  113.          vc = s.v + SLIP_CON / s.v;          // keep accellerating near full power
  114.       else                    // otherwise,
  115.          vc = wl_spd(speed_next, s.v);    // brake for next corner
  116.    else                              // If we're in the curve, maintain speed.
  117.       if(s.to_end * (s.cur_rad + .5 * width) > END_CORNER * width)
  118.                   // if we are far from the next corner, stay at "speed".
  119.          vc = wl_spd(speed, s.v);
  120.       else        // but when we near the next corner, adjust to "speed_next"
  121.          vc = wl_spd(speed_next, s.v);
  122.  
  123.    result.vc = vc;   result.alpha = alpha;
  124.    return result;
  125. }
  126.